package com.example.Service;

import com.example.Controller.Controller;
import javafx.concurrent.Service;
import javafx.concurrent.Task;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

/**
 * 网络通信服务类，负责管理TCP连接、数据传输和状态通知
 * 采用单例模式区分服务器(Server)和客户端(Client)角色
 */
public class NetService {
    // =============== 常量定义 ===============
    private static final int PORT = 13634; // 通信端口号

    // =============== 单例实例 ===============
    private static NetService client;
    private static NetService server;

    // =============== 网络对象成员 ===============
    private Socket socket;                // 网络套接字（客户端/服务器共用）
    private ServerSocket serverSocket;    // 服务器套接字（仅服务器角色使用）
    private InputStream is;               // 输入流（接收数据）
    private OutputStream os;              // 输出流（发送数据）
    private BufferedReader br;            // 缓冲字符输入流（按行读取）
    private PrintWriter pw;               // 打印输出流（按行发送）

    // =============== 状态监听器 ===============
    public NetStateChange nsc;            // 网络状态监听器（回调接口）

    // =============== 单例控制 ===============
    /**
     * 私有构造函数（单例模式）
     */
    private NetService() {}

    /**
     * 获取单例实例（根据角色类型）
     * @param netType 网络角色类型（SERVER/CLIENT）
     * @return 对应的单例实例
     */
    public static NetService getInstance(Controller.NetType netType) {
        switch (netType) {
            case CLIENT:
                if (client == null) {
                    client = new NetService();
                }
                return client;
            case SERVER:
                if (server == null) {
                    server = new NetService();
                }
                return server;
            default:
                return server;
        }
    }

    // =============== 公共接口 ===============
    /**
     * 网络状态变化回调接口
     */
    public interface NetStateChange {
        void onServerOK();        // 服务器启动成功时调用
        void onConnect();         // 连接建立成功时调用
        void onMessage(String msg); // 收到消息时调用
        void onDisconnect();      // 连接断开时调用
    }

    /**
     * 设置网络状态监听器
     * @param nsc 实现NetStateChange接口的监听器
     */
    public void setNetStateChangeListener(NetStateChange nsc) {
        this.nsc = nsc;
    }

    // =============== 连接管理 ===============
    /**
     * 启动服务器监听线程
     */
    public void startServer() {
        new ServerThread().start(); // 启动服务器监听线程
    }

    /**
     * 客户端连接服务器
     * @param ip 服务器IP地址
     */
    public void connectToServer(String ip) {
        try {
            // 创建套接字并连接
            socket = new Socket(ip, PORT);
            init();       // 初始化流对象
            startRead();  // 启动消息读取服务
            // 注意：服务器端的onConnect()在accept成功后触发
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭网络连接并释放资源
     */
    public void close() {
        try {
            // 关闭输出流
            if (pw != null) pw.close();
            // 关闭套接字
            if (socket != null) socket.close();
            // 服务器额外关闭ServerSocket
            if (Controller.netType == Controller.NetType.SERVER) {
                if (serverSocket != null) serverSocket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // =============== 数据传输 ===============
    /**
     * 异步发送消息
     * @param message 要发送的字符串消息
     */
    public void sendMessage(String message) {
        new Thread(() -> {
            pw.println(message); // 写入输出流（自动添加换行）
            pw.flush();          // 强制发送缓冲区数据
        }).start();
    }

    // =============== 内部工具方法 ===============
    /**
     * 初始化网络流对象
     * @throws IOException 流初始化异常
     */
    private void init() throws IOException {
        is = socket.getInputStream();
        os = socket.getOutputStream();
        // 使用UTF-8编码防止乱码
        br = new BufferedReader(new InputStreamReader(is, "utf-8"));
        pw = new PrintWriter(new OutputStreamWriter(os, "utf-8"));
    }

    /**
     * 启动消息读取服务
     */
    private void startRead() {
        ReadThread reader = new ReadThread();
        reader.start();  // 启动JavaFX Service
    }

    /**
     * 同步读取消息（阻塞方法）
     * @return 接收到的消息内容，连接断开时返回null
     */
    private String readMessage() {
        String message = null;
        try {
            message = br.readLine();  // 阻塞读取一行数据
        } catch (SocketException se) {
            // 连接断开处理
            if (nsc != null) {
                nsc.onDisconnect();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return message;
    }

    // =============== 内部线程类 ===============
    /**
     * 服务器监听线程（等待客户端连接）
     */
    class ServerThread extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    // 创建服务器套接字
                    serverSocket = new ServerSocket(PORT);
                    System.out.println(serverSocket.getInetAddress());

                    // 通知UI服务器已就绪
                    if (nsc != null) {
                        nsc.onServerOK();
                    }

                    // 阻塞等待客户端连接
                    socket = serverSocket.accept();
                    init();  // 初始化流对象

                    // 通知UI连接建立
                    if (nsc != null) {
                        nsc.onConnect();
                    }

                    // 启动消息读取服务
                    startRead();
                    break;  // 退出监听循环
                } catch (IOException e) {
                    System.out.print("Server failure\n");
                    e.printStackTrace();
                    try {
                        serverSocket.close();  // 尝试关闭失败端口
                    } catch (IOException ex) {
                        // 忽略关闭异常
                    }
                }
            }
        }
    }

    /**
     * 消息读取服务（JavaFX Service实现）
     * 特点：自动重启读取循环，消息通过回调传递
     */
    class ReadThread extends Service<String> {
        @Override
        protected Task<String> createTask() {
            return new Task<String>() {
                @Override
                protected String call() throws Exception {
                    return readMessage();  // 执行阻塞读取
                }
            };
        }

        @Override
        protected void succeeded() {
            super.succeeded();
            String msg = getValue();
            if (msg != null && !msg.isEmpty()) {
                // 将消息传递给监听器
                if (nsc != null) {
                    nsc.onMessage(msg);
                }
            }
            this.restart();  // 重启服务等待下一条消息
        }
    }
}